#pragma once

#include "../object.h"

#include <queue>
#include <tuple>

namespace bevdet::tracker {

class PHVFilter;

class Tracker {
public:
    explicit Tracker(int64_t id);

    ObjectSptr get(void);
    int64_t getId(void) const;
    ObjectSptr operator->(void);
    Object& operator*(void);
    void fuse(int64_t microTs, const ObjectSptrVector&);
    int32_t getStatus(void) const;

private:
    void setStatus(int32_t);

    void fuseHeader(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fuseId(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fuseSource(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fuseType(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fusePHV(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fuseSize(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fuseColor(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fusePlate(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);
    void fusePlateColor(int64_t microTs, Object& object, const ObjectSptrVector& cameraObjectSptrVector, const ObjectSptrVector& radarObjectSptrVector);

private:
    const int64_t id_ { 0 };
    int64_t index_ { 0 };
    // -1:invalid,0:fused,>0:predict
    int32_t status_ { -1 };
    std::shared_ptr<PHVFilter> phvFilterSptr_ { nullptr };
    // object,cameraObjectSptrVector,radarObjectSptrVector
    std::deque<std::tuple<ObjectSptr, ObjectSptrVector, ObjectSptrVector>> history_;
    // k:type,v:count
    std::unordered_map<int32_t, int32_t> typeStatistician_;
    // k:color,v:count
    std::unordered_map<std::string, int32_t> colorStatistician_;
    // k:plate,v:count
    std::unordered_map<std::string, int32_t> plateStatistician_;
    // k:plateColor,v:count
    std::unordered_map<std::string, int32_t> plateColorStatistician_;
};

}